/*
 * =====================================================================================
 *
 *       Filename:  array.c
 *
 *    Description:  array function implement 
 *
 *        Version:  1.0
 *        Created:  07/20/2011 11:10:13 PM
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Bran Zhang
 *        Company:  Orange'S 
 *
 * =====================================================================================
 */

#include "array.h"

int init_array(Array *pArray, int elem_size, int dim, ...)
{
    assert(NULL != pArray);

    int i, elem_total = 0;
    if (MAX_ARRAY_DIM < dim) {
        printf("error");
        return -3; // error argc
    }

    pArray->dimension = dim;
    
    pArray->bounds = (int *)malloc(sizeof(int) * dim);

    va_list ap;
    va_start(ap, dim);

    for (i = 0; i < dim; ++i) {
        pArray->bounds[i] = va_arg(ap, int);
        if (pArray->bounds[i] < 0) {
            printf("error");
            free(pArray->bounds);
            return -3;
        }
        elem_total += pArray->bounds[i];
        
#ifdef DEBUG
        printf("elem_total is %d, %d = %d\n", elem_total, i, pArray->bounds[i]);
#endif
    }

    va_end(ap);

    pArray->elem_size = elem_size;

    pArray->base = (void *)malloc(elem_size * elem_total);
    if (NULL == pArray->base) {
        fprintf(stderr, "malloce faild\n");
        free(pArray->bounds);
        return -4;
    }

    pArray->constants = (int *)malloc(dim * sizeof(int));
    if (NULL == pArray->constants) {

    }

    pArray->constants[dim - 1] = 1;

    for (int i = dim - 2; i >= 0 ; i--) {
        pArray->constants[i] = pArray->constants[i + 1] * pArray->bounds[i + 1]; 
#ifdef DEBUG
        printf("%d have %d elem num!\n", i, pArray->constants[i]);
#endif
    }

    return 0;
}

void destroy_array(Array *pArray)
{
    free(pArray->base);
    pArray->base = NULL;

    free(pArray->bounds);
    pArray->bounds = NULL;
    
    free(pArray->constants);
    pArray->constants = NULL;

}

int get_value(Array *pArray, void *pElem, ...)
{
    assert((NULL != pArray) && (NULL != pElem)); 
    va_list ap; 
    int i, index = 0, ret;

    va_start(ap, pElem);

    ret = locate_elem(pArray, ap, &index);

    if (ret < 0)
        return -2;

    memcpy(pElem, pArray->base[index], pArray->elem_size);

    return 0;
}

int assign_value(Array *pArray, void *pElem, ...)
{
    assert((NULL != pArray) && (NULL != e));

    return 0;

}

int locate_elem(Array *pArray, va_list ap, int *pOff)
{
    assert((NULL != pArray) && (NULL != pOff));

    int i;
    pOff = 0;
    for (i = 0; i < pArray->dimension; i++) {

        pOff += (va_arg(ap, int) * pArray->constants[i]);
#ifdef DEBUG
        fprintf(stderr, "%d off is %d\n", i, *pOff);
#endif

    }

    return 0;
}

int main(void)
{
    Array array;
    array_init(&array, sizeof(int), 5, 3, 2, 2, 4, 4);
    return 0;
}
